import type { TableIdentity } from 'table-identity';
import type { IQueryParams } from 'vona-module-a-orm';
import type { IRbacScopeAccess } from 'vona-module-a-rbac';
import type { IDecoratorControllerOptions } from 'vona-module-a-web';

import { BeanBase } from 'vona';
import { Api, Resource, v } from 'vona-module-a-openapiutils';
import { z } from 'zod';
import { Passport } from 'vona-module-a-user';
import { Arg, Controller, Web } from 'vona-module-a-web';

import type { Model<%=argv.resourceNameCapitalize%> } from '../model/<%=argv.resourceName%>.ts';

import { $locale } from '../.metadata/locales.ts';
import { Dto<%=argv.resourceNameCapitalize%>Create } from '../dto/<%=argv.resourceName%>Create.tsx';
import { Dto<%=argv.resourceNameCapitalize%>DeleteBulk } from '../dto/<%=argv.resourceName%>DeleteBulk.tsx';
import { Dto<%=argv.resourceNameCapitalize%>SelectReq } from '../dto/<%=argv.resourceName%>SelectReq.tsx';
import { Dto<%=argv.resourceNameCapitalize%>SelectRes } from '../dto/<%=argv.resourceName%>SelectRes.tsx';
import { Dto<%=argv.resourceNameCapitalize%>Update } from '../dto/<%=argv.resourceName%>Update.tsx';
import { Dto<%=argv.resourceNameCapitalize%>View } from '../dto/<%=argv.resourceName%>View.tsx';

export interface IControllerOptions<%=argv.resourceNameCapitalize%> extends IDecoratorControllerOptions {}

@Controller<IControllerOptions<%=argv.resourceNameCapitalize%>>('<%=argv.resourceName%>', {
  summary: $locale('<%=argv.resourceNameCapitalize%>Controller'),
})
@Resource()
export class Controller<%=argv.resourceNameCapitalize%> extends BeanBase {
  @Web.post('', { summary: $locale('<%=argv.resourceNameCapitalize%>Create') })
  @Api.body(v.tableIdentity())
  @Passport.rbac()
  async create(@Arg.body() <%=argv.resourceName%>: Dto<%=argv.resourceNameCapitalize%>Create): Promise<TableIdentity> {
    return (await this.scope.service.<%=argv.resourceName%>.create(<%=argv.resourceName%>)).id;
  }

  @Web.get('', { summary: $locale('<%=argv.resourceNameCapitalize%>Select') })
  @Api.body(Dto<%=argv.resourceNameCapitalize%>SelectRes)
  @Passport.rbac()
  async select(@Arg.filter(Dto<%=argv.resourceNameCapitalize%>SelectReq) params: IQueryParams<Model<%=argv.resourceNameCapitalize%>>): Promise<Dto<%=argv.resourceNameCapitalize%>SelectRes> {
    return await this.scope.service.<%=argv.resourceName%>.select(params);
  }

  @Web.get(':id', { summary: $locale('<%=argv.resourceNameCapitalize%>View') })
  @Api.body(v.optional(), v.object(Dto<%=argv.resourceNameCapitalize%>View))
  @Passport.rbac()
  async view(@Arg.param('id', v.tableIdentity()) id: TableIdentity): Promise<Dto<%=argv.resourceNameCapitalize%>View | undefined> {
    return await this.scope.service.<%=argv.resourceName%>.view(id);
  }

  @Web.patch(':id', { summary: $locale('<%=argv.resourceNameCapitalize%>Update') })
  @Api.body(z.null())
  @Passport.rbac()
  async update(@Arg.param('id', v.tableIdentity()) id: TableIdentity, @Arg.body() <%=argv.resourceName%>: Dto<%=argv.resourceNameCapitalize%>Update): Promise<void> {
    await this.scope.service.<%=argv.resourceName%>.update(id, <%=argv.resourceName%>);
  }

  @Web.delete(':id', { summary: $locale('<%=argv.resourceNameCapitalize%>Delete') })
  @Api.body(z.null())
  @Passport.rbac()
  async delete(@Arg.param('id', v.tableIdentity()) id: TableIdentity): Promise<void> {
    await this.scope.service.<%=argv.resourceName%>.delete(id);
  }

  @Web.post('bulk/delete', { summary: $locale('BulkDelete') })
  @Api.body(z.null())
  @Passport.rbac({ actionInherit: 'delete' })
  async deleteBulk(
    @Arg.body() command: Dto<%=argv.resourceNameCapitalize%>DeleteBulk,
    @Arg.rbacScopeCurrent() rbacScopeCurrent: IRbacScopeAccess,
  ): Promise<void> {
    const entries = await this.bean.rbacResourceBulk.entries(
      command.ids,
      async ids => {
        return await this.scope.model.<%=argv.resourceName%>.select({
          where: rbacScopeCurrent.where({ id: ids }),
        });
      },
      rbacScopeCurrent,
    );
    await this.scope.service.<%=argv.resourceName%>.deleteBulk(entries.map(entry => entry.id));
  }
}
